package com.cliff.joinme.toolkit;

import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;

import org.cybergarage.upnp.Device;
import org.cybergarage.upnp.DeviceList;
import org.cybergarage.upnp.Service;
import org.cybergarage.upnp.event.EventListener;
import org.cybergarage.upnp.event.Subscriber;
import org.cybergarage.upnp.ssdp.SSDPPacket;
import org.cybergarage.upnp.std.av.controller.MediaController;
import org.cybergarage.upnp.std.av.renderer.AVTransport;
import org.cybergarage.upnp.std.av.server.ConnectionManager;
import org.cybergarage.upnp.std.av.server.object.item.ItemNode;
import org.cybergarage.upnp.std.av.server.object.item.ResourceNode;

import com.cliff.joinme.toolkit.MController.URL_TYPE;
import com.cliff.joinme.toolkit.NanoHTTPD.Response;

import android.content.Context;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;

public class ControlPointManager {

	protected static ControlPointManager instance = null;
	protected MController mMediaControlPoint = null;
	protected DeviceList mRendererList = null;
	protected Device mRenderer = null;
	protected HandlerThread threadControlPoint = null;
	protected Handler handler = null;

	protected MicroHTTPD httpd = null;
	protected ArrayList<String> mFileList = null;

	protected final int THREAD_START_CP = 1;
	protected final int THREAD_STOP_CP = 2;
	protected final int THREAD_STOP_RENDERER = 3;
	protected final int THREAD_PLAY_IMAGE = 4;
	protected final int THREAD_PLAY_MUSIC = 5;
	protected final int THREAD_PLAY_VIDEO = 6;

	protected ControlPointManager() {
		mMediaControlPoint = new MController();
		threadControlPoint = new HandlerThread("ControlPoint");
		threadControlPoint.setDaemon(true);
		threadControlPoint.start();
		handler = new Handler(threadControlPoint.getLooper()) {
			@Override
			public void handleMessage(Message msg) {
				// TODO Auto-generated method stub
				switch (msg.what) {
				case THREAD_START_CP:
//					mMediaControlPoint.setNMPRMode(true);
					mMediaControlPoint.start();
					break;
				case THREAD_STOP_CP:
					mMediaControlPoint.stop();
					break;
				case THREAD_STOP_RENDERER:
					mMediaControlPoint.stop(mRenderer);					
					break;
				case THREAD_PLAY_IMAGE:
					mMediaControlPoint.play(mRenderer, httpd.getListUrl(msg.arg1), URL_TYPE.IMAGE, mFileList.get(msg.arg1), (msg.arg2!=0));					
					break;
				case THREAD_PLAY_MUSIC:
					mMediaControlPoint.play(mRenderer, httpd.getListUrl(msg.arg1), URL_TYPE.AUDIO, mFileList.get(msg.arg1), (msg.arg2!=0));
					break;
				case THREAD_PLAY_VIDEO:
					mMediaControlPoint.play(mRenderer, httpd.getListUrl(msg.arg1), URL_TYPE.VIDEO, mFileList.get(msg.arg1), (msg.arg2!=0));
					break;
				}
			}
		};
	}

	@Override
	protected void finalize() throws Throwable {
		// TODO Auto-generated method stub
		if (null != threadControlPoint)
			threadControlPoint.quit();
		super.finalize();
	}

	synchronized public static ControlPointManager getInstance() {
		if (null == instance) {
			instance = new ControlPointManager();

		}
		return instance;
	}

	public void startControlPoint() {
		handler.sendEmptyMessage(THREAD_START_CP);
	}

	public void stopControlPoint() {
		handler.sendEmptyMessage(THREAD_STOP_CP);
	}

	public String getLocalIpAddress() {
		String ipAddr = null;
		try {
			for (Enumeration<NetworkInterface> en = NetworkInterface
					.getNetworkInterfaces(); en.hasMoreElements();) {
				NetworkInterface intf = en.nextElement();
				for (Enumeration<InetAddress> enumIpAddr = intf
						.getInetAddresses(); enumIpAddr.hasMoreElements();) {

					InetAddress inetAddress = enumIpAddr.nextElement();
					if ((!inetAddress.isLoopbackAddress())
							&& (!inetAddress.isLinkLocalAddress())) {
						if (null == ipAddr)
							ipAddr = inetAddress.getHostAddress().toString();
						else
							ipAddr += "/"
									+ inetAddress.getHostAddress().toString();
					}
				}
			}
		} catch (SocketException ex) {
			// Log.e(LOG_TAG, ex.toString());
		}
		return ipAddr;
	}

	public String getSSIDName(Context context) {
		WifiManager wifiMgr = (WifiManager) context
				.getSystemService(Context.WIFI_SERVICE);
		WifiInfo wifiInfo = wifiMgr.getConnectionInfo();
		return wifiInfo.getSSID();
	}

	public DeviceList getRendererList() {
		mRendererList = mMediaControlPoint.getRendererDeviceList();
		return mRendererList;
	}

	public boolean selectRenderer(int position) {
		if (position < 0) {			
			if (null == mRenderer)
				return false;			
			mRenderer = null;
			return true;
		}

		try {
			Device renderer = (Device)mRendererList.get(position);
			if (mRenderer == renderer)
				return false;
			mRenderer = renderer;
			return true;
		} catch (Exception ex) {
			return false;
		}
	}

	public Device getSelectedRenderer() {
		return mRenderer;
	}

	public boolean startHttpd(ArrayList<String> fileList) {
		mFileList = fileList;
		try {
			httpd = new MicroHTTPD(fileList);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			stopHttpd();
			return false;
		}
		return true;
	}

	public boolean stopHttpd() {
		if (null != httpd) {
			httpd.stop();
			mFileList = null;
			httpd = null;
			return true;
		}

		return false;
	}

	public boolean playImage(int pos, boolean stopBeforePlay) {
		if (null == mRenderer)
			return false;

		handler.sendMessage(handler.obtainMessage(THREAD_PLAY_IMAGE, pos, stopBeforePlay?1:0));
		return true;
	}
	
	public boolean playMusic(int pos) {
		if (null == mRenderer)
			return false;

		handler.sendMessage(handler.obtainMessage(THREAD_PLAY_MUSIC, pos, 1));
		return true;
	}

	public boolean playVideo(int pos) {
		if (null == mRenderer)
			return false;

		handler.sendMessage(handler.obtainMessage(THREAD_PLAY_VIDEO, pos, 1));
		return true;
	}

	public boolean stopPlaying() {
		if (null == mRenderer)
			return false;

		handler.sendEmptyMessage(THREAD_STOP_RENDERER);
		return true;
	}

	public String getRendererDisplayName(Device dev) {
		SSDPPacket packet = dev.getSSDPPacket();
//		displayName = dev.getFriendlyName() + "(" + packet.getRemoteAddress() + ":" + packet.getRemotePort() + ")";
		return (dev.getFriendlyName() + "(" + packet.getRemoteAddress() + ")");
	}	
	
	public String[] getTransportState() {
		if (null == mRenderer)
			return null;
		return mMediaControlPoint.getTransportState(mRenderer);
	}
	
	public String[] getPositionInfo() {
		if (null == mRenderer)
			return null;
		return mMediaControlPoint.getPositionInfo(mRenderer);
	}
	
	public boolean subscribeCurrentRenderer(EventListener listener) {
		if (null == mRenderer)
			return false;
		
		mMediaControlPoint.addEventListener(listener);
		return mMediaControlPoint.subscribe(mRenderer.getService(AVTransport.SERVICE_TYPE));
	}
	
	public boolean unsubscribeCurrentRenderer(EventListener listener) {
		mMediaControlPoint.removeEventListener(listener);
		if (null == mRenderer)
			return false;
		
		return mMediaControlPoint.unsubscribe(mRenderer.getService(AVTransport.SERVICE_TYPE));
		
	}
}
